package eerbaar.area;

import java.util.ArrayList;
import java.util.List;

import eerbaar.position.IPosition;
import eerbaar.position.PositionFactory;

public class SquareIterator {

    class Point {
        int x, y;

        Point(int x, int y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public String toString() {
            return "(" + this.x + ", " + this.y + ")";
        }
    }

    private final IPosition start;
    private int index;
    private Point[] rings;
    private IPosition last;

    public SquareIterator(IPosition start) {
        this(start, 10, true);
    }

    public SquareIterator(IPosition start, int radius, boolean includeCenter) {
        this.start = PositionFactory.createPosition(start);
        init(radius, includeCenter);
    }

    public void addRing(List<Point> list, int radius) {

        for (int x = -radius; x <= radius; x++) {
            for (int y = -radius; y <= radius; y++) {
                if (Math.abs(x) == radius || Math.abs(y) == radius) {
                    list.add(new Point(x, y));
                }
            }
        }
    }

    private double calcDistance(IPosition start, IPosition end) {

        final double x1 = start.getX();
        final double y1 = start.getY();
        final double x2 = end.getX();
        final double y2 = end.getY();

        final double xDelta = Math.abs(x1 - x2);
        final double yDelta = Math.abs(y1 - y2);

        final double xPart = (xDelta) * (xDelta);
        final double yPart = (yDelta) * (yDelta);
        final double distance = Math.sqrt(xPart + yPart);

        return distance;
    }

    public double getDistance() {

        if (this.last == null) {
            return 0;
        }

        return calcDistance(this.start, this.last);
    }

    private void init(int radius, boolean includeCenter) {

        if (this.rings != null) {
            return;
        }

        List<Point> list = new ArrayList<Point>();
        if (includeCenter) {
            for (int i = 0; i <= radius; i++) {
                addRing(list, i);
            }
        } else {
            addRing(list, radius - 1);
        }

        this.rings = list.toArray(new Point[] {});
    }

    public IPosition next() {

        int x, y;

        do {
            if (this.index >= this.rings.length) {
                return null;
            }

            Point p = this.rings[this.index];
            this.index++;

            x = this.start.getX();
            y = this.start.getY();

            x += p.x;
            y += p.y;

            this.last = PositionFactory.createPosition(x, y);

            if (x < 0 || x > 9 || y < 0 || y > 9) {
                continue;
            }

            // success
            break;

        } while (true);

        return PositionFactory.createPosition(x, y);
    }

}
